package persistence;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;

public class PersistentProperty {
	private String name;
	private Class<?> clazz;
	private String columnName;
	private String sqlType;
	private boolean id;
	private Method method;
	private PersistentClass persistentClass;
	@SuppressWarnings("serial")
	private static Map<String, String> java2sql = new HashMap<String, String>() {
	    {
	      put("String", "VARCHAR(255)");
	      put("BigDecimal", "NUMERIC");
	      put("Long", "BIGINT");
	      put("int", "INT");
	    }
	  };
	public PersistentProperty(PersistentClass pc, Method m) {
		persistentClass = pc;
		method = m;
		parse();
	}

	
	public void parse() {
		String methodName = method.getName();
		String propertyName = methodName.substring(3, 4).toLowerCase()
				+ methodName.substring(4);
		setName(propertyName);
		Class<?> rclazz = method.getReturnType(); // Types non objet ??
		String javaType = rclazz.getSimpleName();
		setClazz(rclazz);

		Column column = method.getAnnotation(Column.class);
		if(column != null && column.name().length() != 0) {
			setColumnName(column.name());
		} else {
			setColumnName(propertyName);
		}
		if(column != null && column.type().length() != 0) {
			setSqlType(column.type());
		} else {
			setSqlType(java2sql.get(javaType));
		}
		Id id = method.getAnnotation(Id.class);
		if (id != null) {
			setId(true);
			persistentClass.setId(this);
			setSqlType("BIGINT GENERATED ALWAYS AS IDENTITY"); // A généraliser
		}
	}

	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Class<?> getClazz() {
		return clazz;
	}
	public void setClazz(Class<?> clazz) {
		this.clazz = clazz;
	}
	public String getColumnName() {
		return columnName;
	}
	public void setColumnName(String columnName) {
		this.columnName = columnName;
	}
	public String getSqlType() {
		return sqlType;
	}
	public void setSqlType(String sqlType) {
		this.sqlType = sqlType;
	}
	public boolean isId() {
		return this.id;
	}
	public void setId(boolean id) {
		this.id = id;
	}
	protected Method getMethod() {
		return this.method;
	}
	protected void setMethod(Method m) {
		this.method = m;
	}
	public PersistentClass getPersistentClass() {
		return this.persistentClass;
	}
	public void setPersistentClass(PersistentClass pc) {
		this.persistentClass = pc;
	}
	
	
	public Object getValue(Object bean) throws PersistenceException {
		try {
			//System.out.println(bean.getClass() + ": get persistenceProperty " + getName());
			return PropertyUtils.getSimpleProperty(bean, getName());
		} catch (Exception e) {
			throw new PersistenceException("Cannot get property " + getName() + " on object of class " + bean.getClass());
		}
	}
	
	public void setValue(Object bean, Object value) throws PersistenceException {
		Object valueConverted = ConvertUtils.convert(value, getClazz());
		try {
			//System.out.println(bean.getClass() + ": set persistenceProperty " + getName());
			PropertyUtils.setSimpleProperty(bean, getName(), valueConverted);
		} catch (Exception e) {
			throw new PersistenceException("Cannot set property " + getName() + " on object of class " + bean.getClass());
		}
	}
}
